package Tetris;

/** @author Adrian Garcia Rojas
  * @author Aida Ruiz Maya
  * @author Héctor Daniel González Terán
  * @version 1.0 30/12/2010
  * Esta programa es un tetris para el proyecto final de ICC1
  * Profesora de Asignatura: Fernanda Sanchez Puig
  * Ayudante de Laboratorio: Manuel Alcántara Juárez
  */ 

import Tetris.Interfaz.Ventana;
import Tetris.Logica.Figuras.Cuadrado;
import Tetris.Logica.Figuras.Figura;
import Tetris.Logica.Figuras.Palo;
import Tetris.Logica.Figuras.Tetrimino1;
import Tetris.Logica.Figuras.Tetrimino2;
import Tetris.Logica.Figuras.Ttt;
import Tetris.Logica.Figuras.Zeta;
import Tetris.Logica.Figuras.Zeta_Invertida;
import Tetris.Logica.Tablero;
import Tetris.utils.Punto2D;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.util.Random;

public class Tetris {
    private Tablero tablero;
    private Figura[] figuras;
    private Punto2D punto_actual;
    private Figura figura_actual;
    private Random random;
    private boolean gameover;
    private int idFigura;
    public static final int tamPixel = 30;
    private int combo;
    public String frase="";
    private int puntos_anterior;
/**
 * Constructor que crea un objeto Random, uno tablero, uno Punto2D en cierta posicion del tablero
 * Crea un arreglo de todas las figuras disponibles,
 * inicaliza las variables gameover en falso,
 */
    public Tetris() {
        random = new Random();
        gameover = false;
        tablero = new Tablero();
        figuras = new Figura[]{new Ttt(), new Tetrimino2(), new Zeta(), new Zeta_Invertida(), new Cuadrado(), new Tetrimino1(), new Palo()};
        punto_actual = new Punto2D(4, 0);
        idFigura = random.nextInt(figuras.length);
        figura_actual = figuras[idFigura];
    }
/**
 * Este metodo checa mientras no choque abajo a la figura en cuestion la recorre una posicion abajo en la cuadricula
 * si choca con el tablero o con otra figura, pregunta si esta esta hasta arriba y si se traslapa entonces se acaba el juego
 * si no entonces pone una nueva figura en el tablero, manda a llamar actualiza, despues manda a llamar a Puntucion para modificar el score
 * dependiendo de cuantas lineas se eliminaron la matriz en una misma ejecucion del mismo llamado al metodo, despues crea un nuevo objeto Punto2D
 * en el "origen" y manda a poner una nueva figura al azar del arreglo de figuras que teniamos
 */
    public void update() {
        if (!chocaAbajo()) {
            punto_actual = new Punto2D(punto_actual.getX(), punto_actual.getY() + 1);
        } else {
            if (punto_actual.getY() == 0 && translapa()) {
                Ventana.getTimer().stop();
                gameover=true;
            } else {
                ponFiguraTablero();
                tablero.actualiza();
                puntos_anterior=tablero.score;
                Puntuacion(tablero.numLineas);
                combo(tablero.score);
                punto_actual = new Punto2D(4, 0);
                figura_actual.restablece();
                idFigura = random.nextInt(figuras.length);
                figura_actual = figuras[idFigura];
            }
        }
 
    }
/**
 * Mueve el objeto si se presiona en el pad derecha/izquierda respectivamente o lo gira derecha/izquierda dependiendo si se presiono arriba o
 * abajo respectivamente
 * @param key es la variable dependiendo de la tecla precionada
 */
     public void keyPressed(KeyEvent key){
        if (key.getKeyCode() == KeyEvent.VK_RIGHT && !chocaDerecha()) {
                punto_actual = new Punto2D(punto_actual.getX() + 1, punto_actual.getY());
            } else if (key.getKeyCode() == KeyEvent.VK_LEFT && !chocaIzquierda()) {
                punto_actual = new Punto2D(punto_actual.getX() - 1, punto_actual.getY());
            }else if(key.getKeyCode() == KeyEvent.VK_UP){
                figura_actual.rotateRigth();
                if(saleDerecha()||translapa()){
                do{
                    punto_actual = new Punto2D(punto_actual.getX() -1, punto_actual.getY());
                    }while (saleDerecha());
            }
            }else if(key.getKeyCode() == KeyEvent.VK_DOWN){
                figura_actual.rotateLeft();
                if(saleDerecha() || translapa())
                          do{
                    punto_actual = new Punto2D(punto_actual.getX() -1, punto_actual.getY());
                    }while (saleDerecha());
            }
    }
/**
 * Dibuja el tablero, ademas de las figuras dentreo de el
 * @param pinzel
 */
    public void draw(Graphics pinzel) {
        for (int j = 0; j < Tablero.Y_LENGTH; j++) {
            for (int i = 0; i < Tablero.X_LENGTH; i++) {
                if (tablero.get(i, j) != 0) {
                    Figura aux = figuras[tablero.get(i, j) - 1];
                    pinzel.setColor(aux.getFillColor());
                    pinzel.fillRect(i * tamPixel, j * tamPixel, tamPixel, tamPixel);
                    pinzel.setColor(aux.getBorderColor());
                    pinzel.drawRect(i * tamPixel, j * tamPixel, tamPixel, tamPixel);
                }
            }
        }
        Punto2D[] puntosFigura = figura_actual.translate(punto_actual);
        for (int i = 0; i < puntosFigura.length; i++) {
            pinzel.setColor(figura_actual.getFillColor());
            pinzel.fillRect(puntosFigura[i].getX() * tamPixel, puntosFigura[i].getY() * tamPixel, tamPixel, tamPixel);
            pinzel.setColor(figura_actual.getBorderColor());
            pinzel.drawRect(puntosFigura[i].getX() * tamPixel, puntosFigura[i].getY() * tamPixel, tamPixel, tamPixel);
        }
        if(gameover){
            pinzel.setFont(new Font("Book Antiqua",Font.BOLD,40));
            pinzel.setColor(Color.WHITE);
            pinzel.drawString("Game Over",(Tablero.X_LENGTH/4)*(tamPixel-1),(Tablero.Y_LENGTH/2)*tamPixel);
        }
    }
/**
 * Checa si la figura en cuestio no choca con alguna otra pieza que pueda estar abajo de el
 * @return boolean regresa si se traslapa o no la figura
 */
    private boolean translapa() {
        Punto2D[] puntosFigura = figura_actual.translate(new Punto2D(punto_actual.getX(), punto_actual.getY()));
        for (int i = 0; i < puntosFigura.length; i++) {
            if (tablero.get(puntosFigura[i].getX(), puntosFigura[i].getY()) != 0) {
                return true;
            }
        }
        return false;
    }
/**
 * Checa si la figura se sale de el tablero del lado izquierdo
 * @return boolean regresa si la figura se sale del tablero
 */
    private boolean saleDerecha() {
        Punto2D[] puntosFigura = figura_actual.translate(new Punto2D(punto_actual.getX(), punto_actual.getY()));
        for (int i = 0; i < puntosFigura.length; i++) {
            if (puntosFigura[i].getX()>=Tablero.X_LENGTH) {
                return true;
            }
        }
        return false;
    }
/**
 * Pone la figura en el Tablero
 */
    private void ponFiguraTablero() {
        Punto2D[] puntosFigura = figura_actual.translate(punto_actual);
        for (int i = 0; i < puntosFigura.length; i++) {
            tablero.set(puntosFigura[i].getX(), puntosFigura[i].getY(), idFigura + 1);
        }
    }
/**
 * Checa si la figura choca con la parte de abajo del tablero o choca con otra figura debajo de el
 * @return boolean regresa si la figura choca o no con las condiciones antes mencionadas
 */
    private boolean chocaAbajo() {
        Punto2D[] puntosFigura = figura_actual.translate(new Punto2D(punto_actual.getX(), punto_actual.getY()));
        for (int i = 0; i < puntosFigura.length; i++) {
            if (puntosFigura[i].getY() + 1 >= Tablero.Y_LENGTH || tablero.get(puntosFigura[i].getX(), puntosFigura[i].getY() + 1) != 0) {
                return true;
            }
        }
        return false;
    }
/**
 * Checa si la figura choca con la parte izquierda del tablero o con otra figura del lado izquierdo a esta
 * @return boolean regresa si la figura choca o no con las condiciones antes mencionadas
 */
    private boolean chocaDerecha() {
        Punto2D[] puntosFigura = figura_actual.translate(new Punto2D(punto_actual.getX(), punto_actual.getY()));
        for (int i = 0; i < puntosFigura.length; i++) {
            if (puntosFigura[i].getX() + 1 >= Tablero.X_LENGTH || tablero.get(puntosFigura[i].getX() + 1, puntosFigura[i].getY()) != 0) {
                return true;
            }
        }
        return false;
    }
/**
 * Checa si la figura choca con la parte derecha del tablero o con otra figura del lado derecha de esta
 * @return boolean regresa si la figura choca o no con las condiciones antes mencionadas
 */
    private boolean chocaIzquierda() {
        Punto2D[] puntosFigura = figura_actual.translate(new Punto2D(punto_actual.getX(), punto_actual.getY()));
        for (int i = 0; i < puntosFigura.length; i++) {
            if (puntosFigura[i].getX() - 1 < 0 || tablero.get(puntosFigura[i].getX() - 1, puntosFigura[i].getY()) != 0) {
                return true;
            }
        }
        return false;
    }
    /**
     * Modifica el parametro score dependiendo del numero de lineas que se eliminaron por el llamado al metodo actualiza
     * @param numLineas
     */
    public void Puntuacion(int numLineas){
        switch(numLineas){
            case(1):
               tablero.score+=100;
                break;
            case(2):
                tablero.score+=100*2;
                break;
            case (3):
                tablero.score+=100*4;
                break;
            case (4):
                tablero.score+=100*8;
                break;
        }
    }
    /**
     * Regresa el valor del score
     * @return el valor del score
     */
    public int getPuntuacion(){
    return tablero.score;
    }
/**
 * Este metodo realiza el conteo de cuantas lineas consecutivas se eliminan despues de una eliminacion de ellas haciendo con esto un combo
 * @param puntos numero de puntos obtenidos anteriormente
 */
      public void combo(int puntos){
         if(puntos==puntos_anterior){
            combo=0;
            frase="";
        }
            else{
                 combo++;
                switch(combo){
                     case(1):
                        frase="Bien";
                         break;
                     case(2):
                         frase="Muy bien";
                        break;
                     case(3):
                         frase="Fantastico";
                        break;
                     default:
                        frase="Tetris-fantastico";
                }


        }

    }
      /**
       * Regresa el valor del combo
       * @return combo
       */
        public int getCombo(){
            return combo;
        }

        /**
         * Regresa la frase de acuerdo al combo
         * @return frase
         */
        public String getFrase(){
            return frase;
        }

        /**
         * Regresa el numero de lineas eliminadas
         * @return contadorLineas
         */
        public int getLinea(){
            return tablero.contadorLineas;
        }

}